/**
 * 监控数据缓存管理器
 * 负责数据缓存、批量处理和防抖
 */

import type { BaseMonitorData } from '~/types/monitor';
import { ConfigManager } from './config-manager';

interface CacheItem {
  data: BaseMonitorData;
  timestamp: number;
  retryCount: number;
}

export class DataCache {
  private cache: CacheItem[] = [];
  private flushTimer: NodeJS.Timeout | null = null;
  private configManager: ConfigManager;
  private errorCountMap = new Map<
    string,
    { count: number; lastTime: number }
  >();

  constructor() {
    this.configManager = ConfigManager.getInstance();
    this.startFlushTimer();
  }

  /**
   * 添加数据到缓存
   */
  add(data: BaseMonitorData): boolean {
    const config = this.configManager.getConfig();

    // 采样检查
    if (!this.configManager.shouldSample()) {
      return false;
    }

    // 防抖检查 - 相同错误在短时间内只记录一次
    if (data.level === 'error') {
      const errorKey = this.generateErrorKey(data);
      const now = Date.now();
      const errorInfo = this.errorCountMap.get(errorKey);

      if (errorInfo) {
        // 5分钟内相同错误只记录一次，但计数累加
        if (now - errorInfo.lastTime < 300000) {
          errorInfo.count++;
          return false;
        } else {
          // 超过5分钟，重置计数
          errorInfo.count = 1;
          errorInfo.lastTime = now;
        }
      } else {
        this.errorCountMap.set(errorKey, { count: 1, lastTime: now });
      }
    }

    // 缓存大小检查
    if (this.cache.length >= config.maxCacheSize) {
      // 移除最旧的数据
      this.cache.shift();
    }

    // 添加到缓存
    this.cache.push({
      data,
      timestamp: Date.now(),
      retryCount: 0,
    });

    // 如果是严重错误，立即上报
    if (data.level === 'error' || data.level === 'fatal') {
      this.flush();
    }

    return true;
  }

  /**
   * 生成错误唯一标识
   */
  private generateErrorKey(data: BaseMonitorData): string {
    return `${data.type}-${data.message}-${data.url || ''}-${data.line || ''}-${data.column || ''}`;
  }

  /**
   * 获取缓存数据
   */
  getCache(): CacheItem[] {
    return [...this.cache];
  }

  /**
   * 清空缓存
   */
  clear(): void {
    this.cache = [];
  }

  /**
   * 批量上报数据
   */
  flush(): CacheItem[] {
    if (this.cache.length === 0) {
      return [];
    }

    const config = this.configManager.getConfig();
    const batchData = this.cache.splice(0, config.batchSize);

    return batchData;
  }

  /**
   * 重新添加失败的数据
   */
  requeue(items: CacheItem[]): void {
    const config = this.configManager.getConfig();

    items.forEach(item => {
      if (item.retryCount < config.maxRetries) {
        item.retryCount++;
        this.cache.unshift(item); // 添加到队列前面，优先重试
      }
    });
  }

  /**
   * 启动定时上报
   */
  private startFlushTimer(): void {
    const config = this.configManager.getConfig();

    this.flushTimer = setInterval(() => {
      if (this.cache.length > 0) {
        this.flush();
      }
    }, config.flushInterval);
  }

  /**
   * 停止定时上报
   */
  stopFlushTimer(): void {
    if (this.flushTimer) {
      clearInterval(this.flushTimer);
      this.flushTimer = null;
    }
  }

  /**
   * 清理过期的错误计数
   */
  cleanupErrorCounts(): void {
    const now = Date.now();
    const expireTime = 24 * 60 * 60 * 1000; // 24小时

    for (const [key, info] of this.errorCountMap.entries()) {
      if (now - info.lastTime > expireTime) {
        this.errorCountMap.delete(key);
      }
    }
  }

  /**
   * 销毁缓存管理器
   */
  destroy(): void {
    this.stopFlushTimer();
    this.clear();
    this.errorCountMap.clear();
  }
}
